package com.googlecode.rotools.app;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.googlecode.rotools.grf.CardPrefixName;
import com.googlecode.rotools.grf.GrfTool;
import com.googlecode.rotools.grf.ItemDesc;
import com.googlecode.rotools.grf.ItemDisplayName;
import com.googlecode.rotools.grf.ItemParam;
import com.googlecode.rotools.grf.ItemSlot;
import com.googlecode.rotools.grf.ItemSlotCount;
import com.googlecode.rotools.rodb.Item;
import com.googlecode.rotools.rodb.RODB;

public class ImportGRF extends Task<Exception>{
	private List<Task<Exception>> tasks;
	private RODB rodb;
	private File file;
	private GrfTool grfFile;
	
	public ImportGRF() {
		super();
		tasks = new ArrayList<Task<Exception>>();
		tasks.add(new CardPrefixTask());
		tasks.add(new DescriptionTask());
		tasks.add(new UnknownDescriptionTask());
		tasks.add(new NameTask());
		tasks.add(new UnknownNameTask());
		tasks.add(new ParamTask());
		tasks.add(new SlotCountTask());
		tasks.add(new SlotTask());
	}
	public RODB getRodb() {
		return rodb;
	}
	public void setRodb(RODB rodb) {
		this.rodb = rodb;
	}
	public File getGrfFile() {
		return file;
	}
	public void setGrfFile(File file) {
		this.file = file;
	}
	public void run() {
		grfFile = new GrfTool(file);
		for (Task<Exception> task : tasks) {
			task.run();
			Exception result = task.getResult();
			if(result != null){
				setResult(result);
				break;
			}
		}
	}
	private abstract class AbstractTask<T> extends Task<Exception> {
		private Class<T> clazz;
		private String fileName;

		private AbstractTask(Class<T> clazz, String fileName) {
			super();
			this.clazz = clazz;
			this.fileName = fileName;
		}
		public void run() {
			try{
				System.out.println(fileName);
				List<T> list = grfFile.extract(clazz, fileName);
				for (T t : list) {
					String id = getId(t);
					Item item = rodb.getItem(id);
					if(item == null){
						item = new Item();
					}
					marge(item, t);
					rodb.updateItem(item, true);
				}
			}catch(Exception e){
				setResult(e);
			}
		}
		abstract String getId(T t);
		abstract void marge(Item target, T t);
	}
	private class CardPrefixTask extends AbstractTask<CardPrefixName> {
		private CardPrefixTask() {
			super(CardPrefixName.class, "data\\cardprefixnametable.txt");
		}
		@Override
		String getId(CardPrefixName t) {
			return t.getId();
		}
		@Override
		void marge(Item target, CardPrefixName t) {
			target.setId(t.getId());
			target.setCardPrefix(t.getCardPrefix());
		}
	}
	private class DescriptionTask extends AbstractTask<ItemDesc> {
		private DescriptionTask() {
			super(ItemDesc.class, "data\\idnum2itemdesctable.txt");
		}
		@Override
		String getId(ItemDesc t) {
			return t.getId();
		}
		@Override
		void marge(Item target, ItemDesc t) {
			target.setId(t.getId());
			target.setDescription(t.getDescription());
		}
	}
	private class UnknownDescriptionTask extends AbstractTask<ItemDesc> {
		private UnknownDescriptionTask() {
			super(ItemDesc.class, "data\\num2itemdesctable.txt");
		}
		@Override
		String getId(ItemDesc t) {
			return t.getId();
		}
		@Override
		void marge(Item target, ItemDesc t) {
			target.setId(t.getId());
			target.setUnknownDescription(t.getDescription());
		}
	}
	private class NameTask extends AbstractTask<ItemDisplayName> {
		private NameTask() {
			super(ItemDisplayName.class, "data\\idnum2itemdisplaynametable.txt");
		}
		@Override
		String getId(ItemDisplayName t) {
			return t.getId();
		}
		@Override
		void marge(Item target, ItemDisplayName t) {
			target.setId(t.getId());
			target.setName(t.getDisplayName());
		}
	}
	private class UnknownNameTask extends AbstractTask<ItemDisplayName> {
		private UnknownNameTask() {
			super(ItemDisplayName.class, "data\\num2itemdisplaynametable.txt");
		}
		@Override
		String getId(ItemDisplayName t) {
			return t.getId();
		}
		@Override
		void marge(Item target, ItemDisplayName t) {
			target.setId(t.getId());
			target.setUnknownName(t.getDisplayName());
		}
	}
	private class ParamTask extends AbstractTask<ItemParam> {
		private ParamTask() {
			super(ItemParam.class, "data\\itemparamtable.txt");
		}
		@Override
		String getId(ItemParam t) {
			return t.getId();
		}
		@Override
		void marge(Item target, ItemParam t) {
			target.setId(t.getId());
			try{
				target.setWeaponAtk(Integer.parseInt(t.getParam1()));
				
			}catch(NumberFormatException e){
				e.printStackTrace();
			}
			try{
				target.setGuardDef(Integer.parseInt(t.getParam2()));
				
			}catch(NumberFormatException e){
				e.printStackTrace();
			}
		}
	}
	private class SlotCountTask extends AbstractTask<ItemSlotCount> {
		private SlotCountTask() {
			super(ItemSlotCount.class, "data\\itemslotcounttable.txt");
		}
		@Override
		String getId(ItemSlotCount t) {
			return t.getId();
		}
		@Override
		void marge(Item target, ItemSlotCount t) {
			target.setId(t.getId());
			try{
				target.setSlotCount(Integer.parseInt(t.getCount()));
				
			}catch(NumberFormatException e){
				e.printStackTrace();
			}
		}
	}
	private class SlotTask extends AbstractTask<ItemSlot> {
		private SlotTask() {
			super(ItemSlot.class, "data\\itemslottable.txt");
		}
		@Override
		String getId(ItemSlot t) {
			return t.getId();
		}
		@Override
		void marge(Item target, ItemSlot t) {
			target.setId(t.getId());
			try{
				target.setSlot(Integer.parseInt(t.getSlot()));
				
			}catch(NumberFormatException e){
				e.printStackTrace();
			}
		}
	}
}
